home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 9 / FM Towns Free Software Collection 9.iso / t_os / tool / extdrv / src / dir.c < prev    next >
C/C++ Source or Header  |  1994-11-16  |  8KB  |  357 lines

  1. #include "extdrv.h"
  2. #include "ctype.h"
  3. #include "file.h"
  4. #include "dir.h"
  5. #include "buffer.h"
  6. #include "dos.h"
  7. #include "extern.h"
  8.  
  9. extern u_char *dmabuf;
  10. extern u_long ldmabuf;
  11. extern u_short dmabufsize;
  12.  
  13. struct pbuf far *pdirbuf;
  14.  
  15. dir_open(struct drvinfo far *d, char *path, struct dirbuf *bp)
  16. {
  17.     u_char *s, *t, *p;
  18.     u_char buf[MAX_PATH_LEN];
  19.  
  20.     bp->drv = d;
  21.     bp->id = bp->fat = bp->slot = 0;
  22.     if (dir_bread(bp) < 0)
  23.         return (-1);
  24.     strcpy(buf, path);
  25.     t = &buf[1];
  26.     for (s = t; *s != '\0'; s++){
  27.         if (issjis1(s[0]) && issjis2(s[1]))
  28.             s++;
  29.         else if (*s == '\\'){
  30.             p = t;
  31.             *s = '\0';
  32.             if (descend(bp, p) < 0)
  33.                 return(-1);
  34.             t = s + 1;
  35.         }
  36.     }
  37.     return (descend(bp, t));
  38. }
  39.  
  40. static descend(struct dirbuf *bp, char *path)
  41. {
  42.     u_short start;
  43.     struct dirent far *dir;
  44.     char pattern[12];
  45.  
  46.     if (*path == '\0')
  47.         return(0);
  48. #ifdef DEBUG
  49.     auxputs("descend:");
  50. #endif
  51.     expand(path, pattern);
  52. #ifdef DEBUG
  53.     pattern[11] = '\0';
  54.     auxputs(pattern);
  55.     auxputs(" ");
  56. #endif
  57.     while ((dir = dir_read(bp)) != DIR_EOF){
  58.         if (dir->name[0] == IS_EMPTY)
  59.             break;
  60.         if (dir->name[0] == IS_DELETED)
  61.             continue;
  62.         if (!(dir->attr & IS_DIR))
  63.             continue;
  64.         if (dir->name[0] == '.')
  65.             continue;
  66.         if (match(dir->name, pattern)){
  67.             start = dir->start;
  68.                 /* if '..' points to root */
  69.             if (start == 0  &&  strcmp(path, "..") == 0){
  70.                 bp->id = bp->fat = bp->slot = 0;
  71.                 return(dir_bread(bp));
  72.             }
  73.             bp->id = bp->fat = start;
  74.             bp->slot = 0;
  75.             return (dir_bread(bp));
  76.         }
  77.     }
  78. #ifdef DEBUG
  79.     auxputs("\r\n");
  80. #endif
  81.     /*
  82.      * If path is '.' or '..', but they weren't found, then you must be
  83.      * at root.
  84.      */
  85.     if (!strcmp(path, ".") || !strcmp(path, "..")){
  86.         bp->id = bp->fat = bp->slot = 0;
  87.         return (dir_bread(bp));
  88.     }
  89.     return(-1);
  90. }
  91.  
  92. struct dirent far *dir_read(struct dirbuf *dbuf)
  93. {
  94.     int i;
  95.     struct pbuf far *pp;
  96.     u_long src;
  97.     
  98.     if (dbuf->slot == dbuf->n_entry){
  99.         if (dir_next(dbuf) != 0)
  100.             return (NULL);
  101.         dbuf->slot = 0;
  102.     }
  103.     /* search primary buffer */
  104.     for (i = 0, pp = pdirbuf; i < 2; i++, pp++)
  105.         if (pp->drv==dbuf->drv  &&  pp->id==dbuf->id  &&  pp->fat==dbuf->fat)
  106.             break;
  107.     if (dbuf->n_entry < 0  &&  i != 2){
  108.         if (dbuf->id == 0){
  109.             dbuf->buf.rp = pp->buffer.rdir;
  110.             dbuf->n_entry = dbuf->buf.rp->n_entry;
  111.         } else {
  112.             dbuf->buf.bp = pp->buffer.buf;
  113.             dbuf->n_entry = dbuf->drv->dirsec * dbuf->drv->cluster;
  114.         }
  115.     }
  116.     if (i == 2 ||
  117.         (dbuf->slot < pp->offset  ||  pp->offset+pp->n_entry <= dbuf->slot)){
  118.         if (i == 2){ /* not found */
  119.             pp = pdirbuf;
  120.             if (pp->age == 0)
  121.                 pp++;
  122.             if (pp->drv != NULL){
  123.                 if (pp->id == 0)
  124.                     pp->buffer.rdir->pp = NULL;
  125.                 else
  126.                     pp->buffer.buf->pp = NULL;
  127.             }
  128.             if (dir_bread(dbuf) < 0){
  129.                 pp->drv = NULL;
  130.                 return (DIR_EOF);
  131.             }
  132.             pp->drv = dbuf->drv;
  133.             pp->id = dbuf->id;
  134.             pp->fat = dbuf->fat;
  135.             if (dbuf->id == 0){
  136.                 pp->buffer.rdir = dbuf->buf.rp;
  137.                 pp->buffer.rdir->pp = pp;
  138.             } else {
  139.                 pp->buffer.buf = dbuf->buf.bp;
  140.                 pp->buffer.buf->pp = pp;
  141.             }
  142.         }
  143.         pp->offset = dbuf->slot / NDIRPBUF;
  144.         pp->offset *= NDIRPBUF;
  145.         src = (dbuf->id == 0) ? dbuf->buf.rp->buf : dbuf->buf.bp->buf;
  146.         src += pp->offset * sizeof (struct dirent);
  147.         xcopy(src, laddr(pp->data), PBUFSIZE);
  148.         if ((pp->n_entry = NDIRPBUF) > dbuf->n_entry - pp->offset)
  149.             pp->n_entry = dbuf->n_entry - pp->offset;
  150.     }
  151.     pp->age = 0;
  152.     if (pp == pdirbuf)
  153.         (pdirbuf+1)->age = 1;
  154.     else
  155.         pdirbuf->age = 1;
  156.     return ((struct dirent far *)pp->data + (dbuf->slot++ - pp->offset));
  157. }
  158.  
  159. struct dirent far *dir_seek(struct dirbuf *dbuf)
  160. {
  161.     struct dirent far *dir;
  162.     
  163.     dbuf->n_entry = -1;
  164.     dir = dir_read(dbuf);
  165.     dbuf->slot--;
  166.     return (dir);
  167. }
  168.  
  169. dir_write(struct dirbuf *dbuf, struct dirent far *dir)
  170. {
  171.     int i;
  172.     struct pbuf far *pp;
  173.     u_long dst;
  174.  
  175. #ifdef DEBUG
  176.     auxputs("dir_write ");
  177.     auxprinthex((u_long)dbuf->slot);
  178.     auxputs(" ");
  179. #endif
  180.     if (dbuf->id == 0){
  181.         if ((pp = dbuf->buf.rp->pp) != NULL){
  182.             pp->drv = NULL;
  183.             dbuf->buf.rp->pp = NULL;
  184.         }
  185.         dst = dbuf->buf.rp->buf;
  186.     } else {
  187.         if ((pp = dbuf->buf.bp->pp) != NULL){
  188.             pp->drv = NULL;
  189.             dbuf->buf.bp->pp = NULL;
  190.         }
  191.         dst = dbuf->buf.bp->buf;
  192.     }
  193.     dst += dbuf->slot * sizeof (struct dirent);
  194.     xcopy(laddr(dir), dst, sizeof (struct dirent));
  195.     dbuf->slot++;
  196.     dir_dirty(dbuf);
  197.     return (0);
  198. }
  199.  
  200. dir_bread(struct dirbuf *dir)
  201. {
  202.     struct drvinfo far *d;
  203.     u_short id;
  204.     struct rdirbuf far *rp;
  205.     struct buffer far *bp;
  206.     int size;
  207.  
  208.     d = dir->drv;
  209.     id = dir->id;
  210. #ifdef DEBUG
  211.     auxputs("dir_bread:");
  212.     auxprinthex((u_long)id);
  213.     auxputs(",");
  214.     auxprinthex((u_long)dir->fat);
  215.     auxputs(" ");
  216. #endif
  217.     if (id == 0){  /* root dir */
  218.         if ((rp = root_read(d, dir->fat)) == NULL)
  219.             return (-1);
  220.         dir->buf.rp = rp;
  221.         dir->n_entry = rp->n_entry;
  222. #ifdef DEBUG
  223.         auxputs("done.\r\n");
  224. #endif
  225.         return (0);
  226.     }
  227.     if ((bp = bread(d, id, dir->fat, BUF_DIR)) == NULL)
  228.         return (-1);
  229.     dir->buf.bp = bp;
  230.     dir->n_entry = d->dirsec * d->cluster;
  231. #ifdef DEBUG
  232.     auxputs("done.\r\n");
  233. #endif
  234.     return (0);
  235. }
  236.  
  237. dir_next(struct dirbuf *dir)
  238. {
  239.     struct rdirbuf far *rp;
  240.     struct buffer far *bp;
  241.     struct drvinfo far *d;
  242.     u_short next, size;
  243.  
  244. #ifdef DEBUG
  245.     auxputs("dir_next: ");
  246. #endif
  247.     if (dir->id == 0){ /* root dir */
  248.         dir->fat += N_RDIR_ENTRY;
  249.         if ((rp = root_read(dir->drv, dir->fat)) == NULL)
  250.             return (-1);
  251.         dir->buf.rp = rp;
  252.         dir->n_entry = rp->n_entry;
  253.         return (0);
  254.     }
  255.     d = dir->drv;
  256.     if ((next = fat_decode(d, dir->fat)) == 1){
  257. #ifdef DEBUG_ERR
  258.         auxputs("dir_next: fat chain error.\r\n");
  259. #endif
  260.         d->fat_error++;
  261.         return (-1);
  262.     }
  263.     if (next >= d->last_fat)
  264.         return (-1);
  265.     dir->fat = next;
  266.     if ((bp = bread(d, dir->id, next, BUF_DIR)) == NULL)
  267.         return (-1);
  268.     dir->buf.bp = bp;
  269.     return (0);
  270. }
  271.  
  272. dir_bwrite(struct drvinfo far *d, u_short id, u_short fat, struct dirbuf *dir)
  273. {
  274.     struct rdirbuf far *rp;
  275.     struct buffer far *bp;
  276.     int size;
  277.  
  278.     if ((bp = bwrite(d, id, fat, BUF_DIR, TRUE)) == NULL)
  279.         return (-1);
  280.     dir->buf.bp = bp;
  281.     dir->n_entry = d->dirsec * d->cluster;
  282.     dir->drv = d;
  283.     dir->id = id;
  284.     dir->fat = fat;
  285.     dir->slot = 0;
  286.     return (0);
  287. }
  288.  
  289. /*
  290.  * Make a directory entry.  Builds a directory entry based on the
  291.  * name, attribute, starting cluster number, and size.  Returns a pointer
  292.  * to a static directory structure.
  293.  */
  294. void mk_entry(struct dirent far *dir, u_char *filename, u_char attr, 
  295.                 u_short fat, u_long size, u_long now)
  296. {
  297.     int i;
  298.  
  299.     copy_to(filename, 11, dir->name);
  300.     dir->attr = attr;
  301.     for (i = 0; i < 10; i++)
  302.         dir->reserv[i] = 0x00;
  303.     dir->time = now;
  304.     dir->start = fat;
  305.     dir->size = size;
  306. }
  307.  
  308. /*
  309.  * Make a subdirectory grow in length.  Only subdirectories (not root)
  310.  * may grow.  Returns a 0 on success, 1 on failure (disk full), or -1
  311.  * on error.
  312.  */
  313. dir_grow(struct drvinfo far *d, u_short id, u_short fat)
  314. {
  315.     u_short new, entry;
  316.     u_long addr;
  317.     struct dirbuf dBuf;
  318.     struct dirent dir;
  319.  
  320.     if ((new = new_fat(d, 0)) == 1){
  321. #ifdef DEBUG_ERR
  322.         auxputs("dir_grow: FAT error\r\n");
  323. #endif
  324.         d->fat_error++;
  325.         return(-1);
  326.     }
  327.     fat = last_fat(d, fat);
  328.     if (fat_encode(d, fat, new))    /* grow OK ? */
  329.         return (-1);
  330.     if (fat_encode(d, new, d->end_fat)) /* mark EOF OK ? */
  331.         return (-1);
  332.     d->freearea--;
  333.     /* clear new directory cluster */
  334.     if (dir_bwrite(d, id, new, &dBuf) < 0)
  335.         return (-1);
  336.     for (entry = 0; entry < dBuf.n_entry; entry++){
  337.         bzero(&dir, sizeof (struct dirent));
  338.         dir_write(&dBuf, (struct dirent far *)&dir);
  339.     }
  340.     dir_dirty(&dBuf);
  341.     return(0);
  342. }
  343.  
  344. void dir_dirty(struct dirbuf *p)
  345. {
  346.     if (p->id == 0) /* root dir */
  347.         p->buf.rp->dirty = TRUE;
  348.     else
  349.         p->buf.bp->dirty = TRUE;
  350. }
  351.  
  352. void dir_flush(int invalidate)
  353. {
  354.     flush_root(NULL, invalidate);
  355.     flush_buffer(NULL, 0, BUF_DIR, invalidate);
  356. }
  357.